﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using uban.demo.Protocol;

namespace uban.demo
{
    public class Server
    {
        bool _stoped = true;
        TcpListener listener;
        TcpClient client;
        int _port = 8080;
        byte[] buffer = new byte[2048];
        byte[] keyBuffer = new byte[4];
        byte[] loginBuffer = new byte[29];
        byte[] penBuffer = new byte[7];
        /// <summary>
        /// 设备连接事件
        /// </summary>
        public event Action<EndPoint> OnConnet;
        /// <summary>
        /// 异常事件
        /// </summary>
        public event Action<Exception> OnException;
        /// <summary>
        /// 按键事件
        /// </summary>
        public event Action<KeyStatue> OnKeyInfo;
        /// <summary>
        /// 是否已经停止
        /// </summary>
        public bool Stoped
        {
            get
            {
                return _stoped;
            }            
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="port">监听端口</param>
        public Server(int port)
        {
            _port = port;
        }
        /// <summary>
        /// 启动监听（异步）
        /// </summary>
        public bool Start()
        {
            if (!_stoped) return true;
            try
            {

                listener = new TcpListener(IPAddress.Any, _port);
                listener.Start();
                _stoped = false;
                AcceptTcpClient();
                return true;
            }
            catch (Exception ex)
            {
                if (OnException != null)
                {
                    OnException.Invoke(ex);
                }
                return false;
            }
        }

        private void AcceptTcpClient()
        {
            ThreadPool.QueueUserWorkItem(delegate {
                while (!Stoped)
                {
                    try
                    {
                        client = listener.AcceptTcpClient();//接受一个Client  
                        OnAccept(client);
                    }
                    catch (Exception ex)
                    {
                        if (OnException != null)
                        {
                            OnException.Invoke(ex);
                        }
                    }
                }
            });
        }
        /// <summary>
        /// 停止监听
        /// </summary>
        public void Stop()
        {
            if (_stoped) return;
            try
            {
                listener.Stop();
                listener = null;
                _stoped = true;
                client.Close();
            }
            catch (Exception ex)
            {
                if (OnException != null)
                {
                    OnException.Invoke(ex);
                }
            }
        }
        private void OnAccept(TcpClient client)
        {
            if (OnConnet != null)
            {
                OnConnet.BeginInvoke(client.Client.RemoteEndPoint, null, null);
            }
            NetworkStream stream = client.GetStream();//获取网络流  
            bool done = false;
            while (!done && client.Connected)
            {
                int ret = stream.Read(buffer, 0, buffer.Length);//读取网络流中的数据  
                int offset = 0;
                while (ret >= offset + 6)
                {
                    /* 解析类别 */
                    MsgType msg_type = Message.GetInfoType(buffer[0], buffer[1]);
                    switch (msg_type)
                    {
                        case MsgType.InfoType_None:
                            {
                                ++offset;
                            }
                            break;
                        case MsgType.InfoType_Pen:
                            {
                                if (7 > ret - offset)
                                {
                                    offset = ret;
                                    break;
                                }
                                Array.Copy(buffer, offset, penBuffer, 0, 7);
                                PenInput(buffer, offset);
                                offset += 7;
                            }
                            break;
                        case MsgType.InfoType_Online:
                            {
                                if (29 > ret - offset)
                                {
                                    offset = ret;
                                    break;
                                }
                                Array.Copy(buffer, offset, loginBuffer, 0, 29);
                                Login(stream, loginBuffer, offset);
                                offset += 29;
                            }
                            break;
                        case MsgType.InfoType_Tablet_Key:
                            {
                                KeyInut(stream, buffer, offset);
                                offset += 6;
                            }
                            break;
                        case MsgType.InfoType_Mouse_Key:
                            {
                                MouseKeyInfo(stream, buffer, offset);
                                offset += 6;
                            }
                            break;
                        case MsgType.InfoType_Heart:
                            {
                                stream.Write(Message.g_cmd_server_heart, 0, 8);
                                offset += 6;
                            }
                            break;

                    }
                }
            }
        }

        private void MouseKeyInfo(NetworkStream stream,byte[] buffer, int offset)
        {
           
        }  
        private void KeyInut(NetworkStream stream, byte[] buffer, int offset)
        {
            try
            {
                Array.Copy(buffer, offset + 2, keyBuffer, 0, 4);
                byte[] cmd = new byte[8] { 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A };
                Array.Copy(keyBuffer, 0, cmd, 2, 4);
                stream.Write(cmd, 0, 8);
                if (OnKeyInfo != null)
                {
                    KeyStatue key = new KeyStatue(keyBuffer);
                    OnKeyInfo(key);
                }
            }
            catch (Exception ex)
            {
                if (OnException != null)
                {
                    OnException.Invoke(ex);
                }
            }
        }
        public event Action<LoginState> OnLogin;
        private void Login(NetworkStream stream,byte[] buffer, int offset)
        {
            try
            {
                /* 上线成功 */
                stream.Write(Message.g_cmd_bind_success, 0, 14);
                if (OnLogin != null)
                {
                    LoginState state = new LoginState(buffer);
                    OnLogin.BeginInvoke(state, null, null);
                }
            }
            catch (Exception ex)
            {
                if (OnException != null)
                {
                    OnException.Invoke(ex);
                }
            }
        }
        public event Action<PenInputState> OnPenInput;
        private void PenInput(byte [] buffer, int offset)
        {
            try
            {                
                if (OnPenInput != null)
                {
                    PenInputState state = new PenInputState(buffer);
                    OnPenInput.BeginInvoke(state, null, null);
                }
            }
            catch (Exception ex)
            {
                if (OnException != null)
                {
                    OnException.Invoke(ex);
                }
            }
        }

        public void SendSchool(string schoolName)
        {
            if (client != null && client.Connected)
            {
                try
                {
                    NetworkStream stream = client.GetStream();//获取网络流  
                    byte[] school = Encoding.UTF8.GetBytes(schoolName);
                    List<byte> buffer = new List<byte>();
                    buffer.Add(0x88);
                    buffer.Add(0x82);
                    buffer.AddRange(school);
                    buffer.Add(0x0d);
                    buffer.Add(0x0a);
                    stream.Write(buffer.ToArray(), 0, buffer.Count);
                }
                catch (Exception ex)
                {
                    if (OnException != null)
                    {
                        OnException.Invoke(ex);
                    }
                }
            }
        }

        public void SenStudentInfo(string studentName,string studentNo)
        {
            if (client != null && client.Connected)
            {
                try
                {
                    NetworkStream stream = client.GetStream();//获取网络流  
                    byte[] studentInfo = Encoding.UTF8.GetBytes("00000000" + studentName + studentNo);
                    List<byte> buffer = new List<byte>();
                    buffer.Add(0x88);
                    buffer.Add(0x81);
                    buffer.AddRange(studentInfo);
                    buffer.Add(0x0d);
                    buffer.Add(0x0a);
                    stream.Write(buffer.ToArray(), 0, buffer.Count);
                }
                catch (Exception ex)
                {
                    if (OnException != null)
                    {
                        OnException.Invoke(ex);
                    }
                }
            }
        }        
    }   
}
